package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.constant.WorkOrderConstant;
import com.tbit.main.dao.log.PowerChangeLogDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.StringUtil;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 换电记录
 *
 * @author Leon
 * 2019年11月12日 下午4:47:36
 */
@Service("powerChangeLogService")
public class PowerChangeLogServiceImpl implements PowerChangeLogService {
    @Autowired
    private PowerChangeLogDao powerChangeLogDao;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private DataService dataService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private MachineOpLogService machineOpLogService;
    @Autowired
    private PowerChangePerformanceService powerChangePerformanceService;

    @Override
    public Integer insert(PowerChangeLog powerChangeLog) {
        Integer insert = powerChangeLogDao.insert(powerChangeLog);

        // 插入车辆操作日志
        AccountUser accountUser = accountUserService.getById(powerChangeLog.getUserMainId());
        machineOpLogService.insertSingle(MachineOpLog.builder()
                .accountId(powerChangeLog.getAccountId())
                .machineId(powerChangeLog.getMachineId())
                .machineNO(powerChangeLog.getMachineNO())
                .userCode(powerChangeLog.getUserCode())
                .operation("换电")
                .opUser(accountUser.getName())
                .opUserPhone(accountUser.getPhone())
                .opPlatform(OperationPlatform.MAINTAIN.code)
                .result(true)
                .opTime(LocalDateTime.now())
                .build());

        // 插入换电绩效
        powerChangePerformanceService.calculateAndInsertPerformance(powerChangeLog);

        return insert;
    }

    @Override
    public List<PowerChangeLogSta> groupByTime(Integer agentId, Integer userType, Integer usermainId,
                                               String startTime, String endTime, List<Integer> regionId, Integer machineType, Integer isValid) {
        List<PowerChangeLogSta> pclses;

        /**查询代理商运维账号*/
        List<Integer> accountUserIds = new ArrayList<>();
        /**判断当前账号是不是运维人员*/
        if (roleService.getRoleCode(userType).equals(1)) {
            accountUserIds.add(usermainId);
        }

        Map<String, Object> params = new HashMap<>();
        params.put(DaoParamConstant.accountId, agentId);
        params.put("userMainIds", StringUtil.getListString(accountUserIds));
        params.put("isValid", isValid);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        if (CollUtil.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(usermainId);
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));
        params.put("machineType", machineType);
        pclses = powerChangeLogDao.groupByTime(params);

        List<Integer> userMainIds = pclses.stream().map(PowerChangeLogSta::getUserMainId).collect(Collectors.toList());
        Map<Integer, AccountUser> accountUserMap = accountUserService.getByIds(userMainIds)
                .stream().collect(Collectors.toMap(AccountUser::getAccountUserId, Function.identity()));

        List<PowerChangeLogSta> pclseFilters = new ArrayList<>();
        for (PowerChangeLogSta pcls : pclses) {
            Optional.ofNullable(accountUserMap.get(pcls.getUserMainId()))
                    .ifPresent(au -> {
                        pcls.setName(au.getName());
                        pcls.setPhone(au.getPhone());
                        pcls.setDelFlag(au.getDelFlag());
                        pclseFilters.add(pcls);
                    });
        }

        return pclseFilters;
    }

    @Override
    public List<PowerChangeLog> getByTime(Integer accountId, Integer userMainId, String startTime, String endTime, List<Integer> regionId,
                                          Integer machineType, Integer isValid, String userCode, String batteryNO, String batteryNOOld) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("userMainId", userMainId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put("isValid", isValid);
        params.put(DaoParamConstant.endTime, endTime);
        if (StrUtil.isNotBlank(userCode)) {
            params.put("machineId", dataService.getMachineIdUserCode(userCode));
        }
        if (CollUtil.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(userMainId);
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));
        params.put("machineType", machineType);

        List<PowerChangeLog> powerChangeLogs;
        if (StrUtil.isBlank(batteryNO) && StrUtil.isBlank(batteryNOOld)) {
            powerChangeLogs = powerChangeLogDao.getByTime(params);
        } else {
            params.put("batteryNO", batteryNO);
            params.put("batteryNOOld", batteryNOOld);
            powerChangeLogs = powerChangeLogDao.getByTimeBatteryNO(params);
        }

        List<Integer> accountUserIds = powerChangeLogs.stream().map(PowerChangeLog::getAuditorId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(accountUserIds)) {
            List<AccountUser> accountUsers = accountUserService.getByIds(accountUserIds);
            Map<Integer, String> accountUserMap = new HashMap<>();
            for (AccountUser accountUser : accountUsers) {
                accountUserMap.put(accountUser.getAccountUserId(), accountUser.getName());
            }

            for (PowerChangeLog powerChangeLog : powerChangeLogs) {
                if (powerChangeLog.getAuditorId() == null || powerChangeLog.getAuditorId().equals(WorkOrderConstant.sys_auditor)) {
                    powerChangeLog.setAuditorName(WorkOrderConstant.sys_auditorName);
                } else {
                    powerChangeLog.setAuditorName(accountUserMap.get(powerChangeLog.getAuditorId()));
                }
            }
        }

        return powerChangeLogs;
    }

    @Override
    public Integer getByAccountIdTime(Integer accountId, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        return powerChangeLogDao.getByAccountIdTime(params);
    }

    @Override
    public Integer getByRegionIdTime(Integer regionId, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("regionId", regionId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        return powerChangeLogDao.getByRegionIdTime(params);
    }

    @Override
    public List<Map<String, Object>> getGroupByDay(Integer accountId, String statDate, String endDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("statDate", statDate);
        params.put("endDate", endDate);

        return powerChangeLogDao.getGroupByDay(params);
    }

    @Override
    public List<PowerChangeLog> getPowerChangeLogIds(List<Integer> powerChangeLogIds) {
        List<PowerChangeLog> power = new LinkedList<>();
        List<List<Integer>> powerIds = ListUtils.partition(powerChangeLogIds, 900);
        for (List<Integer> powerChangeLogId : powerIds) {
            power.addAll(powerChangeLogDao.getPowerChangeLogIds(StringUtil.getListString(powerChangeLogId)));
        }
        return power;
    }

    @Override
    public PowerChangeLog getPowerChangeLogId(Integer powerChangeLogId) {
        return powerChangeLogDao.getPowerChangeLogId(powerChangeLogId);
    }

    @Override
    public void update(Integer powerChangeLogId, Integer newSoc, Integer isValid, String remark, String auditTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("powerChangeLogId", powerChangeLogId);
        map.put("newSoc", newSoc);
        map.put("isValid", isValid);
        map.put("remark", remark);
        map.put("auditTime", auditTime);
        powerChangeLogDao.update(map);
    }

    @Override
    public List<PowerChangeLog> getByMachineIdTime(Integer machineId, String time, Integer isValid) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", machineId);
        map.put("time", time);
        map.put("isValid", isValid);
        return powerChangeLogDao.getByMachineIdTime(map);
    }

    @Override
    public Integer workOrder(String userCode) {

        Machine machine = machineService.getByUseCode(userCode);

        if (machine != null) {
            AccountConfig accountConfig = dataService.getAccountConfig(machine.getAccountId());
            if (accountConfig != null) {
                List<PowerChangeLog> powerChangeLogs = new LinkedList<>();
                List<RideLog> rideLogs = new LinkedList<>();
                if ((accountConfig.getRide() != null && accountConfig.getRide() != 0) ||
                        (accountConfig.getRideDistance() != null && accountConfig.getRideDistance() != 0)) {
                    powerChangeLogs = getByMachineIdTime(machine.getMachineId(), null, 1);
                    if (powerChangeLogs != null && powerChangeLogs.size() > 0) {
                        rideLogs = rideLogService.getMachineIdStartTime(machine.getMachineId(), powerChangeLogs.get(0).getChangeTime(), null);
                    } else {
                        rideLogs = rideLogService.getMachineIdStartTime(machine.getMachineId(), null, DateTimeUtil.getNowTime());
                    }
                }

                /**判断两个工单内有订单*/
                if (accountConfig.getRide() != null && accountConfig.getRide() != 0) {
                    if (rideLogs != null && rideLogs.size() > 0) {
                    } else {
                        return 1;
                    }
                }

                /**判断两个工单的距离距离*/
                if (accountConfig.getRideDistance() != null && accountConfig.getRideDistance() != 0) {

                    double distance = 0;
                    for (RideLog rideLog : rideLogs) {
                        distance = distance + rideLog.getMileage();
                    }

                    if (distance * 1000 < accountConfig.getRideDistance()) {
                        return 2;
                    }
                }

                /**判断两个工单之间的时间*/
                if (accountConfig.getLogTime() != null && accountConfig.getLogTime() != 0) {
                    List<PowerChangeLog> powerChangeLog = getByMachineIdTime(machine.getMachineId(), DateTimeUtil.getMinsAgo(accountConfig.getLogTime()), 1);
                    if (powerChangeLog != null && powerChangeLog.size() > 0) {
                        return 3;
                    }
                }

            } else {
                return 0;
            }
        } else {
            throw new BaseException("Machine.notExist");
        }
        return 0;
    }

    @Override
    public void updatePcl(PowerChangeLog powerChangeLog) {
        powerChangeLogDao.updatePcl(powerChangeLog);
    }
}
